package POE::Data::Envelope;

use warnings;
use strict;
use Carp;

our $VERSION = '0.02';

use constant
{
    'DATA'  => 0,
    'OOB'   => 1,
    'ERROR' => 2,
};

use overload 
(
    '@{}'   => \&array_deref,
    '""'    => \&stringification,
);

sub stringification
{
    my $class = ref($_[0]);
    
    bless($_[0], 'overload::dummy');
    my $ref = $_[0]->[+DATA];
    bless($_[0], $class);
    return "$ref";
}

sub array_deref 
{ 
    my $class = ref($_[0]);
    bless($_[0], 'overload::dummy');
    my $data = $_[0]->[+DATA];
    bless($_[0], $class);
    return $data;
}

sub data()
{
    my $class = ref($_[0]);
    
    bless($_[0], 'overload::dummy');

    my $data;

    if(@_ > 1)
    {
        if(@_ == 2)
        {
            if(ref($_[1]) =~ /ARRAY/o)
            {
                $_[0]->[+DATA] = $_[1];
            
            } elsif(ref($_[1])) {
                
                bless($_[0], $class);
                Carp::croak('Only array references may be stored');
            
            } else {
                
                $data = $_[0]->[+DATA]->[$_[1]];
            }
        
        } elsif(@_ == 3) {
            
            $_[0]->[+DATA]->[$_[1]] = $_[2];
        }
    
    } else {
        
        $data = $_[0]->[+DATA];
    }

    bless($_[0], $class);
    return $data;
}

sub oob()
{
    my $class = ref($_[0]);
    
    bless($_[0], 'overload::dummy');

    my $data;

    if(@_ > 1)
    {
        $_[0]->[+OOB] = $_[1];
    
    } else {

        $data = $_[0]->[+OOB];
    }

    bless($_[0], $class);
    return $data;
}

sub error()
{
    my $class = ref($_[0]);
    
    bless($_[0], 'overload::dummy');

    my $data;
    
    if(@_ > 1)
    {
        $_[0]->[+ERROR] = $_[1];
    
    } else {

        $data = $_[0]->[+ERROR];
    }

    bless($_[0], $class);
    return $data;
}

sub new()
{
    my ($class, $data, $oob, $error) = @_;
    
    my $self = [];
    $self->[+DATA] = $data ? $data : [];
    $self->[+OOB] = $oob ? $oob : [];
    $self->[+ERROR] = $error ? $error : 0;
    bless($self, $class);

    return $self;
}

sub clone()
{
    my $class = ref($_[0]);
    
    bless($_[0], 'overload::dummy');

    my $clone = [];
    
    $clone->[+DATA] = [];
    @{$clone->[+OOB]} = @{$_[0]->[+OOB]};
    $clone->[+ERROR] = $_[0]->[+ERROR];
    
    bless($_[0], $class);
    bless($clone, $class);

    return $clone;
}

1;

__END__

=pod

=head1 NAME

POE::Data::Envelope - An envelope class to be used with Filters that need to
report out of band data to the consumer of the filtered data.

=head1 VERSION

Version 0.01

=head1 SYNOPSIS

This class is ultimately just a very thin Class::Struct-like object with an 
overloaded array dereference to accommodate legacy filters and applications 
that do not expect to receive an Envelope object.
    
    package Some::Filter;

    use POE::Data::Envelope;

    sub get_one()
    {
        ...
        # If error
        my $envelope = POE::Data::Envelope->new();
        $envelope->oob('There are no records');
        $envelope->error(1);
        return $envelope;
    }

=head1 AUTHOR

Nicholas Perez, C<< <nperez at cpan.org> >>

=head1 METHODS

=over 4

=item new()

new() takes no arguments and returns an envelope object.

=item oob()

oob() can take and store any arbitrary scalar reference, and return it if no
arguments are provided. This is useful for sending data out of the normal flow
to report a problem to downstream consumers.

=item error()

error() can take and store any arbitrary scalar reference, and return it if no
arguments are provided. If there is an error in processing within the filter
set this to a positive value to let the downstream consumers adjust program
behavior accordingly.

=back 

=head1 BUGS

Please report any bugs or feature requests to
C<bug-poe-data-envelope at rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=POE-Data-Envelope>.
I will be notified, and then you'll automatically be notified of progress on
your bug as I make changes.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc POE::Data::Envelope

You can also look for information at:

=over 4

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/POE-Data-Envelope>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/POE-Data-Envelope>

=item * RT: CPAN's request tracker

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=POE-Data-Envelope>

=item * Search CPAN

L<http://search.cpan.org/dist/POE-Data-Envelope>

=back

=head1 ACKNOWLEDGEMENTS

=head1 COPYRIGHT & LICENSE

Copyright 2007 Nicholas Perez, all rights reserved.

This program is released under the following license: gpl

=cut

